#pragma once 
#include "epoll.hpp"
#include "connection.hpp"
#include <unordered_map>

class Reactor
{

private:
    bool Conisexit(int fd)
    {
        auto it = _connections.find(fd);
        if (it == _connections.end())
        {
            use_log(loglevel::DEBUG) << "con is not exit!";
            return false;
        }
        else
            return true;
    }
    // 再重载一个second版本的查找
    bool Conisexit(shared_ptr<Connection> &pcon)
    {
        int fd = pcon->GetSockFd();
        auto it = _connections.find(fd);
        if (it == _connections.end())
        {
            use_log(loglevel::DEBUG) << "con is not exit!";
            return false;
        }
        else
            return true;
    }
    void Dispatcher(int n)
    {

        for (int i = 0; i < n; i++)
        {
            int fd = _res[i].data.fd;
            int events = _res[i].events;
            // 将所有的异常处理，统一转化成IO错误,这里必须先处理错误后处理读写时间关心，否则转化不了
            if (events & EPOLLERR)
                events |= (EPOLLIN | EPOLLOUT);
            if (events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);

            if (events & EPOLLIN)
            { //说明接收缓冲区有数据了
                if (Conisexit(fd))
                {
                    _connections[fd]->Recver();
                }
            }
            if (events & EPOLLOUT)
            {
                //说明发送缓冲区有位置了
                
                if (Conisexit(fd))
                {     
                    _connections[fd]->Sender();
                }
            }
        }
    }

public:
    Reactor() : _isrunning(0), _epoller_ptr(make_unique<Epoll>())
    {
    }
    void loop()
    {
        _isrunning = 1;
        int timeout = -1;
        while (_isrunning)
        {
              
            int n = _epoller_ptr->Waitevent(_res, 128, timeout);

            // 交给事件派发器处理：
            Dispatcher(n);
        }
        _isrunning = 0;
    }
    void Addconnection(shared_ptr<Connection> &pcon)
    {
        if (Conisexit(pcon))
        {
            use_log(loglevel::DEBUG) << "con is  exit!";
            return;
        }
        // 不存在，进行添加
        pcon->Setowner(this);
        // 进行epoll写入内核：
        _epoller_ptr->Addevent(pcon->GetSockFd(), pcon->Getevents());
        // map管理起来
        _connections[pcon->GetSockFd()] = pcon;
    }
    void Delconnection(int fd)
    {
        _epoller_ptr->Delevent(fd, _connections[fd]->Getevents());
        _connections.erase(fd);
        close(fd);
    }
    void CareReadWrite(int fd, bool rd, bool we)
    {
        if (!Conisexit(fd))
        {
            use_log(loglevel::DEBUG) << "con is not exit!";
            return;
        }
        int events = _connections[fd]->Getevents();
        int finalevents = events | (rd == 1 ? EPOLLIN: 0) | (we == 1 ? EPOLLOUT : 0);
        _connections[fd]->Setevents(finalevents);
        //勿忘epoll灌入内核：
        _epoller_ptr->Modevent(fd,finalevents);
    }
    void stop()
    {
        _isrunning = 0;
    }

    ~Reactor() {}

private:
    unique_ptr<Epoll> _epoller_ptr;
    unordered_map<int, shared_ptr<Connection>> _connections;
    bool _isrunning;
    struct epoll_event _res[128];
};